use model_graph_channel::http_request as remote_http_request;
use model_graph_common::transport::http::http_post;
use model_graph_types::{
    assistant::chat::{ChatMessage, ChatOptions, ChatProvider},
    channel::{HttpRequest, HttpResponse},
};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

pub async fn chat_request(
    provider: ChatProvider,
    messages: Vec<ChatMessage>,
    options: ChatOptions,
) -> anyhow::Result<Vec<ChatMessage>> {
    tracing::debug!("请求chat接口:{:?}", provider);
    let url = &provider.url;
    let token_key = &provider.token_key;
    let token = &provider.token;

    let mut headers = HashMap::new();
    headers.insert(
        String::from("Content-Type"),
        String::from("application/json"),
    );

    //TOKEN
    if let Some(token) = token {
        //
        if let Some(token_key) = token_key {
            headers.insert(token_key.clone(), token.clone());
        } else {
            headers.insert(String::from("Authorization"), token.clone());
        }
    }

    let body = if let Some(request_jmespath) = &provider.request_jmespath {
        let messages_value = if request_jmespath != "" {
            //
            // let expr = jmespath::compile(request_jmespath.as_str())?;
            // let result = expr.search(serde_json::json!({
            //     "messages": messages
            // }))?;
            serde_json::to_string(&serde_json::json!({
                "model": _get_model(&provider, &options)?,
                "messages": messages
            }))?
        } else {
            serde_json::to_string(&serde_json::json!({
                "model": _get_model(&provider, &options)?,
                "messages": messages
            }))?
        };
        messages_value
    } else {
        serde_json::to_string(&serde_json::json!({
            "model": _get_model(&provider, &options)?,
            "messages": messages
        }))?
    };
    tracing::debug!("message:{}", body);

    let timeout = if let Some(time) = &options.timeout {
        *time as u64
    } else {
        120000u64
    };

    //
    let response = if let Some(peer) = &provider.peer {
        tracing::debug!("调用节点CHAT服务:{}", peer);
        //调用节点
        let request: HttpRequest =
            HttpRequest::post(url.clone(), headers, Some(body.into_bytes()))?;
        let response_result = remote_http_request(&peer.clone(), request, timeout).await;
        match response_result {
            Ok(response) => {
                if response.status == 200 {
                    tracing::debug!("请求成功:{:?}", response);
                    Ok(response.body)
                } else {
                    Err(anyhow::anyhow!("请求失败!"))
                }
            }
            Err(err) => Err(anyhow::anyhow!("请求失败!{}", err)),
        }
    } else {
        //直接本地请求
        let response_result = http_post(url, &headers, body.into_bytes()).await;
        match response_result {
            Ok((_, _, response)) => Ok(response),
            Err(err) => Err(anyhow::anyhow!("请求失败!{}", err)),
        }
    };
    match response {
        Ok(response) => {
            tracing::debug!(
                "返回的数据:{}",
                String::from_utf8(response.clone()).unwrap()
            );

            let res_messages: Vec<ChatMessage> =
                if let Some(response_jmespath) = &provider.response_jmespath {
                    if response_jmespath != "" {
                        //
                        // let expr = jmespath::compile(response_jmespath.as_str())?;
                        // let data = jmespath::Variable::from_json(
                        //     String::from_utf8(response.clone())
                        //         .map_err(|err| anyhow::anyhow!("{}", err))?
                        //         .as_str(),
                        // )
                        // .map_err(|err| anyhow::anyhow!("{}", err))?;
                        // let result = expr.search(data)?;
                        // tracing::debug!("{}", result);
                        // serde_json::from_value(serde_json::json!(result))
                        //     .map_err(|err| anyhow::anyhow!("{}", err))?
                        vec![]
                    } else {
                        //转换json
                        let res_messages: OpenAIChatResponse = serde_json::from_slice(&response)?;

                        res_messages
                            .choices
                            .iter()
                            .map(|item| ChatMessage::assistant(item.message.content.clone()))
                            .collect()
                    }
                } else {
                    //转换json
                    let res_messages: OpenAIChatResponse = serde_json::from_slice(&response)?;

                    res_messages
                        .choices
                        .iter()
                        .map(|item| ChatMessage::assistant(item.message.content.clone()))
                        .collect()
                };

            return Ok(res_messages);
        }
        Err(err) => Ok(vec![ChatMessage::assistant(format!("抱歉!{}", err))]),
    }
}

fn _get_model(provider: &ChatProvider, options: &ChatOptions) -> anyhow::Result<String> {
    if let Some(model) = &options.model {
        return Ok(model.clone());
    }

    if let Some(model) = provider.options.get("model") {
        return Ok(model.clone());
    }

    Ok(String::from("gpt-3.5-turbo"))
}

#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
struct OpenAIChoiceMessage {
    pub role: Option<String>,
    pub content: String,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
struct OpenAIChoice {
    pub index: Option<i32>,
    pub message: OpenAIChoiceMessage,
    pub finish_reason: Option<String>,
}

#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
struct OpenAIChatResponse {
    pub choices: Vec<OpenAIChoice>,
}
